import fs from 'node:fs';
import path from 'node:path';
import { CONFIG } from '../config.js';
import { DataBundle, SeriesRow } from '../shared/types.js';
import { logInfo } from '../utils/log.js';
import { ymdToDate } from '../utils/date.js';

function ensureDir(dir: string) { if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); }

function activePath(ts_code: string) {
  ensureDir(CONFIG.STORAGE.ACTIVE_DIR);
  return path.join(CONFIG.STORAGE.ACTIVE_DIR, `${ts_code}.json`);
}

function archiveYearDir(ts_code: string, year: number) {
  const dir = path.join(CONFIG.STORAGE.ARCHIVE_DIR, ts_code);
  ensureDir(dir);
  return path.join(dir, `${year}.json`);
}

export function readBundle(ts_code: string): DataBundle | null {
  const fp = activePath(ts_code);
  if (!fs.existsSync(fp)) return null;
  try { return JSON.parse(fs.readFileSync(fp, 'utf-8')); } catch { return null; }
}

export function writeBundle(ts_code: string, bundle: DataBundle) {
  const fp = activePath(ts_code);
  fs.writeFileSync(fp, JSON.stringify(bundle, null, 2), 'utf-8');
}

export function mergeSeries(oldSeries: SeriesRow[] | undefined, newSeries: SeriesRow[]): SeriesRow[] {
  const merged = [...(oldSeries || [])];
  const set = new Set((oldSeries || []).map(s => s.trade_date));
  for (const s of newSeries) if (!set.has(s.trade_date)) merged.push(s);
  merged.sort((a, b) => a.trade_date.localeCompare(b.trade_date));
  return merged;
}

export function archiveOld(ts_code: string, series: SeriesRow[], keepYears = 1): SeriesRow[] {
  if (series.length === 0) return series;
  const lastDate = series[series.length - 1].trade_date;
  const lastYear = ymdToDate(lastDate).getUTCFullYear();
  const minYear = lastYear - keepYears + 1; // keep current and previous (if keepYears>1)

  const remain: SeriesRow[] = [];
  const byYear: Record<number, SeriesRow[]> = {};
  for (const s of series) {
    const y = ymdToDate(s.trade_date).getUTCFullYear();
    if (y >= minYear) { remain.push(s); continue; }
    if (!byYear[y]) byYear[y] = [];
    byYear[y].push(s);
  }

  // write archives
  for (const yStr of Object.keys(byYear)) {
    const y = Number(yStr);
    const fp = archiveYearDir(ts_code, y);
    fs.writeFileSync(fp, JSON.stringify(byYear[y], null, 2), 'utf-8');
    logInfo(`归档 ${ts_code} 年份 ${y} 共 ${byYear[y].length} 条`);
  }

  return remain;
}

export function loadAllSeries(ts_code: string): SeriesRow[] {
  const active = readBundle(ts_code);
  const list: SeriesRow[] = active?.series || [];
  const dir = path.join(CONFIG.STORAGE.ARCHIVE_DIR, ts_code);
  if (fs.existsSync(dir)) {
    for (const f of fs.readdirSync(dir)) {
      if (!f.endsWith('.json')) continue;
      const fp = path.join(dir, f);
      try {
        const rows: SeriesRow[] = JSON.parse(fs.readFileSync(fp, 'utf-8'));
        list.push(...rows);
      } catch {}
    }
  }
  list.sort((a, b) => a.trade_date.localeCompare(b.trade_date));
  return list;
}